package com.leaf.spring.y201906.day19.springboot;

import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationListener;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.ClassUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;

/**
 * 模拟springboot启动，初始化，Listener
 *@Title:  
 *@Description:  
 *@Author: leaf  
 *@Since:2019年6月19日  
 *@Version:1.1.0
 */
//SpringFactoriesLoader
public class PropertiesLoaderUtilsTest {

	public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/leaf.factories";

	// loadSpringFactories
	public static void main(String[] args) {
		
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

		try {
			// SpringFactoriesLoader.loadFactoryNames 返回类名集合
			MultiValueMap<String, String> result = new LinkedMultiValueMap<>();

			// 读取文件
			Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);

			while (urls.hasMoreElements()) {

				URL url = urls.nextElement();

				UrlResource urlResource = new UrlResource(url);

				// 获取资源文件
				Properties properties = PropertiesLoaderUtils.loadProperties(urlResource);

				for (Map.Entry<?, ?> entry : properties.entrySet()) {

					String key = ((String) entry.getKey()).trim();

					for (String value : StringUtils.commaDelimitedListToStringArray((String) properties.get(key))) {
						result.add(key, value.trim());
					}

				}

			}

			// createSpringFactoriesInstances

			List<String> ll = result.getOrDefault(ApplicationListener.class.getName(), Collections.EMPTY_LIST);

			List<Object> list = new ArrayList<>();

			for (String l : ll) {

				Class<?> clazz = ClassUtils.forName(l, classLoader);

				// 获取构造器
				Constructor<?> constructor = clazz.getDeclaredConstructor(new Class<?>[] {});

				// 实例化
				Object obj = BeanUtils.instantiateClass(constructor, args);

				list.add(obj);

			}

			System.out.println(list.size());

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
